﻿/**
//  GetPropertyCommand.cs
//  Marquee Moment
//  Copyright 2011 Systematix Technocrates. All rights reserved.
**/
using System;
using System.Runtime.InteropServices;
using EDSDKLib;
using MarqueeMoment.CameraController.Camera;

namespace MarqueeMoment.CameraController.Command
{
    public class GetPropertyCommand : Command
    {


        private uint propertyID;

        public GetPropertyCommand(CameraModel model, uint propertyID)
            : base(model)
        {
            this.propertyID = propertyID;
        }

        //// Execute a command.	
        public override bool execute()
        {

            uint err = EDSDK.EDS_ERR_OK;
            bool locked = false;

            //// You should do UILock when you send a command to camera models elder than EOS30D.

            if (base.model.isLegacy())
            {
                err = EDSDK.EdsSendStatusCommand(base.model.getCameraObject(), EDSDK.CameraState_UILock, 0);


                if (err == EDSDK.EDS_ERR_OK)
                {
                    locked = true;

                }

            }

            ////Get a property.

            if (err == EDSDK.EDS_ERR_OK)
            {
                err = getProperty(this.propertyID);

            }


            if (locked)
            {
                err = EDSDK.EdsSendStatusCommand(base.model.getCameraObject(), EDSDK.CameraState_UIUnLock, 0);

            }

            //// Notify Error.

            if (err != EDSDK.EDS_ERR_OK)
            {
                //// Retry when the camera replys deviceBusy.

                if ((err + EDSDK.EDS_ERRORID_MASK) == EDSDK.EDS_ERR_DEVICE_BUSY)
                {
                    base.model.notifyObservers(commandName.warn, err);

                    return false;

                }

                base.model.notifyObservers(commandName.errr, err);

            }

            return true;

        }


        private uint getProperty(uint id)
        {
            uint err = EDSDK.EDS_ERR_OK;
            EDSDK.EdsDataType dataType = EDSDK.EdsDataType.Unknown;
            int dataSize = 0;


            if (id == EDSDK.PropID_Unknown)
            {
                //// If the propertyID is invalidID,
                //// you should retry to get properties.
                //// InvalidID is able to be published for the models elder than EOS30D.

                if (err == EDSDK.EDS_ERR_OK)
                {
                    err = getProperty(EDSDK.PropID_AEMode);
                }
                if (err == EDSDK.EDS_ERR_OK)
                {
                    err = getProperty(EDSDK.PropID_Tv);
                }
                if (err == EDSDK.EDS_ERR_OK)
                {
                    err = getProperty(EDSDK.PropID_Av);
                }
                if (err == EDSDK.EDS_ERR_OK)
                {
                    err = getProperty(EDSDK.PropID_ISOSpeed);
                }
                if (err == EDSDK.EDS_ERR_OK)
                {
                    err = getProperty(EDSDK.PropID_ImageQuality);
                }

                return err;
            }

            //// Get propertysize.

            if (err == EDSDK.EDS_ERR_OK)
            {
                err = EDSDK.EdsGetPropertySize(base.model.getCameraObject(), id, 0, out dataType,out dataSize);

            }


            if (err == EDSDK.EDS_ERR_OK)
            {
                int data = 0;
                if (dataType == EDSDK.EdsDataType.UInt32)
                {
                    //// Get a property.
                    IntPtr ptr = Marshal.AllocHGlobal(dataSize);

                    err = EDSDK.EdsGetPropertyData(base.model.getCameraObject(), id, 0, dataSize, ptr);

                    data = (int)Marshal.PtrToStructure(ptr, typeof(int));
                    Marshal.FreeHGlobal(ptr);


                    if (err == EDSDK.EDS_ERR_OK)
                    {
                        base.model.setPropertyUInt32(id, data);

                    }
                }


                if (dataType == EDSDK.EdsDataType.String)
                {
                    string str = null;
                    //char[EDS_MAX_NAME]
                    IntPtr ptr = Marshal.AllocHGlobal(EDSDK.EDS_MAX_NAME);

                    //// Get a property.
                    err =  EDSDK.EdsGetPropertyData(base.model.getCameraObject(), id, 0, dataSize, ptr);

                    str = Marshal.PtrToStringAnsi(ptr);
                    Marshal.FreeHGlobal(ptr);

                    //// Stock the property .

                    if (err == EDSDK.EDS_ERR_OK)
                    {
                        base.model.setPropertyString(id, str);

                    }
                }

            }


            //// Notify updating.

            if (err == EDSDK.EDS_ERR_OK)
            {
                base.model.notifyObservers(commandName.updt, id);

            }

            return err;

        }

    }
}
